//
//  AHBuilder.swift
//  AttributedStringHelper
//
//  Created by JY_NEW on 2021/11/1.
//

import Foundation

@resultBuilder
public struct AHBuilder {
    public static func buildBlock(_ segments: AHBuildable...) -> AHBuildable {
        return AHBuildArray(items: segments)
    }
    public static func buildIf(_ item: AHBuildable?) -> AHBuildable  {
        return item ?? AHBuildNone()
    }
    public static func buildEither(first: AHBuildable) -> AHBuildable {
        return first
    }
    public static func buildEither(second: AHBuildable) -> AHBuildable {
        return second
    }
    public static func buildArray(_ components: [AHBuildable]) -> AHBuildable {
        return AHBuildArray(items: components)
    }
}

extension NSAttributedString {
    public convenience init(_ string: String, _ settings: AHSetting...) {
        self.init(string: string, attributes: settings.attributes())
    }
    public class func create(_ settings: AHSetting..., @AHBuilder build: () -> AHBuildable) -> NSMutableAttributedString {
        return .init(settings: settings, build: build)
    }
}

extension NSMutableAttributedString {
    public convenience init(_ settings: AHSetting..., @AHBuilder build: () -> AHBuildable ) {
        self.init(settings: settings, build: build)
    }
    public convenience init(settings: [AHSetting], @AHBuilder build: () -> AHBuildable ) {
        let builder = build()
        var items: [AHBuildItem]
        if let array = builder.__attributedStringHelperPerformBuildItems() {
            items = array
        }else if let item = builder.__attributedStringHelperPerformBuildItem() {
            items = [item]
        }else {
            items = []
        }
        let string = items.reduce(into: "") { partialResult, item in
            switch item {
            case let .string(text, _): partialResult += text
            default:break
            }
        }
        self.init(string: string, attributes: settings.attributes())
        var index = 0
        for item in items {
            switch item {
            case let .string(text, attrs):
                if let attrs = attrs {
                    self.addAttributes(attrs, range: NSMakeRange(index, text.count))
                }
                index += text.count
            case let .attributedString(text):
                self.insert(text, at: index)
                index += text.length
            }
        }
    }
}
